package uk.ac.lkl.lpp.model;



import java.util.List;


public abstract class FieldGroup<O> implements Comparable<FieldGroup<O>> {

    private static int NEXT_ID = 0;

    private List<O> list;

    // ids used for purposes of comparison
    private int id;


    public FieldGroup(List<O> list) {
        this.list = list;
        this.id = NEXT_ID++;
    }


    public abstract boolean isPermanent();


    public final boolean isEditable(int listIndex, int fieldIndex) {
        O element = list.get(listIndex);
        return isEditable(element, fieldIndex);
    }


    public abstract boolean isEditable(O element, int fieldIndex);


    public Object getField(int listIndex, int fieldIndex) {
        O element = list.get(listIndex);
        // check fieldIndex is in range for size()
        return getField(listIndex, element, fieldIndex);
    }


    protected abstract Object getField(int listIndex, O element, int fieldIndex);


    public void setField(int listIndex, int fieldIndex, Object object) {
        // check is instance of getClass();
        O element = list.get(listIndex);
        Class cl = getClass(fieldIndex);
        if (!cl.isInstance(object))
            return;

        setField(element, fieldIndex, object);
    }


    public abstract String getName();


    protected abstract void setField(O element, int fieldIndex, Object object);


    public abstract String getFieldName(int fieldIndex);


    public Object getHeader(int fieldIndex) {
        return getFieldName(fieldIndex);
    }


    protected abstract Class getClass(int fieldIndex);


    protected Class getHeaderClass(int fieldIndex) {
        return String.class;
    }


    public abstract int size();


    public List<O> getList() {
        return list;
    }


    public int compareTo(FieldGroup<O> other) {
        return this.id - other.id;
    }


    /**
     * If total makes no sense, should return null.
     * 
     * Should be same class as field.
     * 
     * @return
     * 
     */
    public abstract Object calculateTotal(int fieldIndex);

}
